#include "sms_server.h"
#include "event2/event.h"
#include <cstring>
#include "event2/listener.h"
#include <iostream>
#include "work_group.h"
#include "com/simple_logger.h"

using namespace std;

static void SConnListenerCb(struct evconnlistener *listen, evutil_socket_t sock, struct sockaddr *addr, int len, void *ctx)
{
    // 解析客户端ip
    char ip[16] = {0};
    sockaddr_in *addr_in = (sockaddr_in *)addr;
    evutil_inet_ntop(AF_INET, &addr_in->sin_addr, ip, sizeof(ip));
    stringstream ss;
    ss << ip << ":" << addr_in->sin_port << " 连接完成...";
    LOG4CPLUS_INFO(SimpleLogger::Get()->LoggerRef(), ss.str());
    SmsServer *server = (SmsServer *)ctx;
    int s = sock;

    server->ConnListener(s);
}

SmsServer::SmsServer(int port, int thread_num, int backlog)
    : port_(port),
      thread_num_(thread_num),
      backlog_(backlog)
{
}

SmsServer::~SmsServer()
{
    Stop();
}

thread *SmsServer::GetThread() const
{
    return dispatch_thread_;
}

bool SmsServer::Init()
{
    // 创建事件循环
    ev_base_ = event_base_new();
    if (!ev_base_)
    {
        return false;
    }
    sockaddr_in sin;
    memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(port_);
    // 创建socket连接回调
    ev_listener_ = evconnlistener_new_bind(
        ev_base_,
        SConnListenerCb,
        this,
        LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE,
        this->backlog_,
        (sockaddr *)&sin,
        sizeof(sin));
    if (!ev_listener_)
    {
        return false;
    }
    // 创建线程组管理类
    boss_ = new WorkGroup(thread_num_);
    boss_->Init();
    return true;
}

void SmsServer::Start()
{
    if (!dispatch_thread_)
    {
        server_quit_ = false;
        // 在线程中分发
        dispatch_thread_ = new thread(&SmsServer::Dispatch, this);
    }
}

void SmsServer::Stop()
{
    if (boss_)
    {
        // 退出线程组
        boss_->ExitSafety();
        delete boss_;
        boss_ = nullptr;
    }
    if (dispatch_thread_)
    {
        // 退出线程和事件循环
        server_quit_ = true;
        dispatch_thread_->join();
        delete dispatch_thread_;
        dispatch_thread_ = nullptr;
        LOG4CPLUS_INFO(SimpleLogger::Get()->LoggerRef(), "服务停止");
    }
}

void SmsServer::Dispatch()
{
    stringstream ss;
    ss << "SmsServer开始监听端口：" << port_;
    LOG4CPLUS_INFO(SimpleLogger::Get()->LoggerRef(), ss.str());
    // 事件分发并循环处理
    while (!server_quit_)
    {
        event_base_loop(ev_base_, EVLOOP_NONBLOCK);
        this_thread::sleep_for(chrono::milliseconds(1));
    }
    evconnlistener_free(ev_listener_);
    event_base_free(ev_base_);
    ev_base_ = nullptr;
    ev_listener_ = nullptr;
}

void SmsServer::ConnListener(int socket)
{
    // 新连接交给线程组处理
    boss_->CreateConnection(socket);
}
